说一下 select、poll、epoll
10 分钟阅读
•
1142 字
+
639 词
总结:
- select: select是一个 最古老的I/O多路复用机制 ,它可以监视多个文件描述符的可读、可写和错误状态。然而,但是它的效率可能随着监视的文件描述符数量的增加而降低。因为select使用 fd_set位图 来进行监听, 将需要监听的文件描述符放入这个fd_set中 ,让 内核来检查是否有⽹络事件产⽣ ,检查的⽅式很粗暴,就是通过 遍历⽂件描述符集合的⽅式 ,当 检查到有事件产⽣后 ,将 此 Socket 标记为可读或可写 , 接着再把 整个⽂件描述符集合拷⻉回⽤户态 ⾥,然后**⽤户态 还需要再 通过遍历的⽅法(每个判断if ISSET)找到可读或可写的 Socket**,然后再对其处理。所以, 对于 select 这种⽅式,需要进⾏ 2 次「遍历」⽂件描述符集合,⼀次是在内核态⾥,⼀次是在⽤户态⾥ ,⽽且还会发⽣ 2 次「拷⻉」⽂件描述符集合,先从⽤户空间传⼊内核空间,由内核修改后,再传出到⽤户空间中。fd_set的固定大小是1024 ,所以监听的数量有限,并且 监听和就绪是耦合 的。
-
poll:
poll是select的一种改进,它使用
轮询方式
来检查多个文件描述符的状态,
避免了select中文件描述符数量有限的问题,不再使用位图
,而是
使用动态数组,以链表的形式来组织
。监听和返回的集合也进行了分离,但对于大量的文件描述符,poll的性能也可能变得不足够高效,因为
需要全部遍历所有的文件描述符
。
- poll比起select,改进了文件描述数量有限制的问题,使用链表来组织文件描述符,并且对监听和返回的集合也进行了分离。但是还是需要遍历全部的文件描述符检查可读可写 。
-
epoll:
- epoll是Linux特有的I/O多路复用机制,相较于select和poll,它在处理大量文件描述符时更加高效 。epoll 使用事件通知的方式 , 只有在文件描述符就绪时才会通知应用程序 ,而 不需要轮询 。并且 监听集合 采用 红黑树 ,不用像select那样每次操作都传入整个集合,而是传入检测的fd就行,大小无限制,并且 监听和就绪分离 , 只需遍历就绪集合即可,不用遍历所有的文件描述符 。
- epoll 使⽤ 事件驱动的机制 , 内核⾥维护了⼀个链表来记录就绪事件 ,当某个socket 有事件发⽣时,通过 回调函数内核 会将其加⼊到这个 就绪事件链表 中,当**⽤户调⽤epoll_wait() 函 数时,只会 返回有事件发⽣的⽂件描述符的个数**,不需要像 select/poll 那样轮询扫描整个 socket 集合,⼤⼤提⾼了检测的效率。